package service.thread;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeBodyPart;

import service.FileUtil;
import service.ThreadUtil;


public class SortMessagesThreadPool {
	
	private int threadCount = Runtime.getRuntime().availableProcessors();
	private List<Message> listMessages;
	private List<Message> listMessagesToDelete;
	private List<Thread> listThread;
	
	public SortMessagesThreadPool(List<Message> listMessages) {
		this.listMessages = listMessages;
		this.listThread = new ArrayList<>(this.threadCount);
		this.listMessagesToDelete = new LinkedList<>();
	}
	
	public List<Message> execute() {
		
		List<List<Message>> splitedListMessages = this.splitList();
		
		/*
		for (List<Message> messages : splitedListMessages) {
			this.listThread.add(new SepareteMessageThread(messages, this.listMessagesToDelete));
		}
		*/
		
		for (int i = 0; i < threadCount; i++) {
			this.listThread.add(new SepareteMessageThread(this.listMessages, this.listMessagesToDelete));
		}

		ThreadUtil.startThreads(this.listThread);
		
		return this.listMessagesToDelete;
	}
	
	private List<List<Message>> splitList() {

		int[] arrayMaxIndex = this.generateIndexs(this.listMessages);
		List<List<Message>> list = new ArrayList<>(this.threadCount);
		int end = 0;
		int start = 0;

		for (int i = 0; i < this.threadCount; i++) {
			end += (arrayMaxIndex[i]);
			list.add(new ArrayList<>(this.listMessages.subList(start, end)));
			start += arrayMaxIndex[i];
		}

		return list;
	}

	private int[] generateIndexs(List<Message> listMessages) {

		int value = listMessages.size() / this.threadCount;
		
		int[] arrayMaxIndex = new int[this.threadCount];

		for (int i = 0; i < this.threadCount; i++) {
			arrayMaxIndex[i] = value;
		}
		arrayMaxIndex[this.threadCount - 1] += listMessages.size() % threadCount;

		return arrayMaxIndex;
	}
	
}

class SepareteMessageThread extends Thread {

	private List<Message> listMessages;
	private List<Message> listMessagesToDelete;
	
	public SepareteMessageThread(List<Message> listMessages, List<Message> listMessagesToDelete) {
		this.listMessages = listMessages;
		this.listMessagesToDelete = listMessagesToDelete;
	}
	
	@Override
	public void run() {

		try {
			synchronized (this) {
				this.separateMessages();				
			}
		} catch (MessagingException | IOException e) {
			e.printStackTrace();
		}
	}
	
	private void separateMessages() throws MessagingException, IOException {
		
		for (Message message : this.listMessages) {
			if ((this.hasNoAttachment(message.getContentType()) || (this.hasNoXmlAttachment(message)))) {
				this.listMessagesToDelete.add(message);
			} 
		}				
	}

	private boolean hasNoAttachment(String content) {
		return !content.contains("multipart/MIXED");
	}
	
	private boolean hasNoXmlAttachment(Message message) throws IOException, MessagingException {

		Multipart multipart = (Multipart) message.getContent();			
		
		for (int i = 0; i < multipart.getCount(); i++) {
			
			MimeBodyPart mimeBodyPart = (MimeBodyPart) multipart.getBodyPart(i);
			
			if (Part.ATTACHMENT.equalsIgnoreCase(mimeBodyPart.getDisposition())) {
				
				if  (FileUtil.isXmlFile(mimeBodyPart.getFileName())) {
					return false;
				}
			}
		}
		
		return true;
	}
}